home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
iritsm3s.zip
/
INPTEVAL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-30
|
66KB
|
1,884 lines
/*****************************************************************************
* "Irit" - the 3d polygonal solid modeller. *
* *
* Written by: Gershon Elber Ver 0.2, Mar. 1990 *
******************************************************************************
* Module to evaluate the binary tree generated by the InptPrsr module. *
* All the objects are handled the same but the numerical one, which is *
* moved as a RealType and not as an object (only internally within this *
* module) as it is frequently used and consumes much less memory this way. *
* Note this module is par of InptPrsr module and was splited only because *
* of text file sizes problems... *
*****************************************************************************/
#ifdef __MSDOS__
#include <alloc.h>
#include <dir.h>
#endif /* __MSDOS__ */
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "convex.h"
#include "ctrl-brk.h"
#include "dataprsr.h"
#include "dosintr.h"
#include "freeform.h"
#include "geomat3d.h"
#include "geomvals.h"
#include "graphgen.h"
#include "inptprsg.h"
#include "inptprsl.h"
#include "matherr.h"
#include "objects.h"
#include "overload.h"
#include "primitiv.h"
#include "viewobj.h"
#include "windows.h"
InptPrsrEvalErrType IPGlblEvalError = IPE_NO_ERR;/* Global used by EvalTree. */
extern char IPGlblCharData[LINE_LEN_LONG]; /* Used for both parse & eval. */
/* I prefer to put the declarations of static functions just before the */
/* function themselves, but the tables below needs them so... */
static int FetchParameters(ParseTree *Root, int NumParams, int Level,
ParseTree *Params[]);
static void PrintHelp(char *HelpHeader);
static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
ParseTree *PBody);
static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
ParseTree *PBody);
static ObjectStruct *GenObjectList(ParseTree *PObjParams);
static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams);
static int CountNumExpressions(ParseTree *Root);
static ParseTree *FetchExpression(ParseTree *Root, int i, int n);
static int RetrieveMathError(void);
static int CountNumParameters(ParseTree *Root);
static ParseTree *FetchParameter(ParseTree *Root, int i, int n);
static int FuncParamMismatch(ParseTree *Root);
static void LocalPrintTree(ParseTree *Root, int Level, char *Str);
static void RebindVariable(ParseTree *Root, ObjectStruct *PObj);
static int RetrieveMathError(void);
/* Although the type of parameters is specified (for InptPrsrTypeCheck rtn) */
/* All the parameters to the following dispatched functions are passed by */
/* address. There is a problem in TurboC (ANSI C?) that all the real types */
/* are passed as double, even if the are float. As RealType may be float, */
/* the problems is hidden by passing parameters by address... */
NumFuncTableType NumFuncTable[] = {
{ "ACOS", ARCCOS, acos, 1, { NUMERIC_EXPR } },
{ "ASIN", ARCSIN, asin, 1, { NUMERIC_EXPR } },
{ "ATAN2", ARCTAN2, atan2, 2, { NUMERIC_EXPR, NUMERIC_EXPR } },
{ "ATAN", ARCTAN, atan, 1, { NUMERIC_EXPR } },
{ "COS", COS, cos, 1, { NUMERIC_EXPR } },
{ "EXP", EXP, exp, 1, { NUMERIC_EXPR } },
{ "ABS", FABS, fabs, 1, { NUMERIC_EXPR } },
{ "LN", LN, log, 1, { NUMERIC_EXPR } },
{ "LOG", LOG, log10, 1, { NUMERIC_EXPR } },
{ "SIN", SIN, sin, 1, { NUMERIC_EXPR } },
{ "SQRT", SQRT, sqrt, 1, { NUMERIC_EXPR } },
{ "TAN", TAN, tan, 1, { NUMERIC_EXPR } },
{ "CPOLY", CPOLY, PolyCountPolys, 1, { POLY_EXPR } },
{ "AREA", AREA, PolyObjectArea, 1, { POLY_EXPR } },
{ "VOLUME", VOLUME, PolyObjectVolume, 1, { POLY_EXPR } },
{ "TIME", TIME, DosGetTime, 1, { NUMERIC_EXPR } },
};
int NumFuncTableSize = sizeof(NumFuncTable) / sizeof(NumFuncTableType);
ObjFuncTableType ObjFuncTable[] = {
{ "VECTOR", VECTOR, GenVecObject, 3, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CTLPT", CTLPT, CtlPtFromParams, ANY_PARAM_NUM, { 0 } },
{ "ROTX", ROTX, GenMatObjectRotX, 1, { NUMERIC_EXPR } },
{ "ROTY", ROTY, GenMatObjectRotY, 1, { NUMERIC_EXPR } },
{ "ROTZ", ROTZ, GenMatObjectRotZ, 1, { NUMERIC_EXPR } },
{ "TRANS", TRANS, GenMatObjectTrans, 1, { VECTOR_EXPR } },
{ "SCALE", SCALE, GenMatObjectScale, 1, { VECTOR_EXPR } },
{ "BOX", BOX, GenBOXObject, 4, { VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "GBOX", GBOX, GenGBOXObject, 4, { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
{ "CONE", CONE, GenCONEObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
{ "CON2", CONE2, GenCONE2Object, 4, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CYLIN", CYLIN, GenCYLINObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
{ "SPHERE", SPHERE, GenSPHEREObject, 2, { VECTOR_EXPR, NUMERIC_EXPR } },
{ "TORUS", TORUS, GenTORUSObject, 4, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CIRCPOLY", CIRCPOLY, GenPLANEObject, 3, { VECTOR_EXPR, VECTOR_EXPR, NUMERIC_EXPR } },
{ "POLY", POLY, GenPOLYGONObject, 1, { OLST_EXPR } },
{ "CROSSEC", CROSSEC, GenCROSSECObject, 1, { POLY_CURVE_EXPR } },
{ "SURFREV", SURFREV, GenSURFREVObject, 1, { POLY_CURVE_EXPR } },
{ "EXTRUDE", EXTRUDE, GenEXTRUDEObject, 2, { POLY_CURVE_EXPR, VECTOR_EXPR } },
{ "LIST", LIST, GenObjectList, ANY_PARAM_NUM, { 0 } },
{ "LOAD", LOAD, DataPrsrGetObjects, 1, { STRING_EXPR } },
{ "CONVEX", CONVEX, ConvexPolyObjectN, 1, { POLY_EXPR } },
{ "SBEZIER", SBEZIER, GenBezierSurfaceObject, 1, { OLST_EXPR } },
{ "CBEZIER", CBEZIER, GenBezierCurveObject, 1, { OLST_EXPR } },
{ "SBSPLINE", SBSPLINE, GenBsplineSurfaceObject, 4, { NUMERIC_EXPR, NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
{ "CBSPLINE", CBSPLINE, GenBsplineCurveObject, 3, { NUMERIC_EXPR, OLST_EXPR, OLST_EXPR } },
{ "SEVAL", SEVAL, EvalSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CEVAL", CEVAL, EvalCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
{ "STANGENT", STANGENT, TangentSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CTANGENT", CTANGENT, TangentCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
{ "SNORMAL", SNORMAL, NormalSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "SDIVIDE", SDIVIDE, DivideSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CDIVIDE", CDIVIDE, DivideCurveObject, 2, { CURVE_EXPR, NUMERIC_EXPR } },
{ "SREGION", SREGION, RegionFromSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "CREGION", CREGION, RegionFromCurveObject, 3, { CURVE_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "SREFINE", SREFINE, RefineSurfaceObject, 4, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ, OLST_EXPR } },
{ "CREFINE", CREFINE, RefineCurveObject, 3, { CURVE_EXPR, NUMERIC_OBJ, OLST_EXPR } },
{ "SRAISE", SRAISE, RaiseSurfaceObject, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
{ "CRAISE", CRAISE, RaiseCurveObject, 2, { CURVE_EXPR, NUMERIC_OBJ } },
{ "CSURFACE", CSURFACE, CurveFromSurface, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
{ "CMESH", CMESH, CurveFromSrfMesh, 3, { SURFACE_EXPR, NUMERIC_OBJ, NUMERIC_OBJ } },
{ "NTH", NTH, GetNthList, 2, { OLST_EXPR, NUMERIC_EXPR } },
{ "GPOLYGON", GPOLYGON, Geometry2Polygons, 1, { OLST_GEOM_EXPR } },
{ "GPOLYLINE", GPOLYLINE, Geometry2Polylines, 1, { OLST_GEOM_EXPR } },
{ "CIRCLE", CIRCLE, GenCircleCurveObject, 2, { VECTOR_EXPR, NUMERIC_EXPR } },
{ "ARC", ARC, GenArcCurveObject, 3, { VECTOR_EXPR, VECTOR_EXPR, VECTOR_EXPR } },
{ "RULEDSRF", RULEDSRF, GenRuledSrfObject, 2, { CURVE_EXPR, CURVE_EXPR } },
{ "BOOLSUM", BOOLSUM, GenBoolSumSrfObject, 4, { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR, CURVE_EXPR } },
{ "SFROMCRVS", SFROMCRVS, GenSrfFromCrvsObject, 1, { OLST_EXPR } },
{ "SWEEPSRF", SWEEPSRF, GenSweepSrfObject, 3, { CURVE_EXPR, CURVE_EXPR, CURVE_EXPR | NUMERIC_EXPR } },
{ "OFFSET", OFFSET, GenOffsetObject, 2, { CURVE_EXPR | SURFACE_EXPR, NUMERIC_EXPR } },
{ "CEDITPT", CEDITPT, EditCrvControlPoint, 3, { CURVE_EXPR, CTLPT_EXPR, NUMERIC_EXPR } },
{ "SEDITPT", SEDITPT, EditSrfControlPoint, 4, { SURFACE_EXPR, CTLPT_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "MERGEPOLY",MERGEPOLY, GenObjectFromPolyList, 1, { OLST_EXPR } },
};
int ObjFuncTableSize = sizeof(ObjFuncTable) / sizeof(ObjFuncTableType);
/* The cast for DosSystem below is because of the xlc compiler for the R6000 */
/* aix system complains on DosSystem as function with no arguments, so we */
/* make it think it has one integer argument... */
typedef void (*VoidFuncIntPtr)(int);
GenFuncTableType GenFuncTable[] = {
{ "EXIT", EXIT, MyExit, 0, { 0 } },
{ "VIEW", VIEW, WndwViewGeomObject, 2, { OLST_GEOM_EXPR, NUMERIC_EXPR } },
{ "DIR", DIR, DosPrintDir, 1, { STRING_EXPR } },
{ "CHDIR", CHDIR, DosChangeDir, 1, { STRING_EXPR } },
{ "NORMAL", NORMAL, ViewSetNormals, 3, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR } },
{ "INCLUDE", INCLUDE, FileInclude, 1, { STRING_EXPR } },
{ "SAVE", SAVE, DataPrsrPutObject, 2, { STRING_EXPR, ANY_EXPR } },
{ "FREE", FREEOBJ, FreeObject, 1, { ANY_EXPR } },
{ "INTERACT", INTERACT, InteractPolyObject, 2, { OLST_GEOM_EXPR, NUMERIC_EXPR } },
{ "PAUSE", PAUSE, WndwPause, 1, { NUMERIC_EXPR } },
{ "IF", IFCOND, IfCondition, 4, { NUMERIC_EXPR, STRING_EXPR, NUMERIC_EXPR, ANY_EXPR } },
{ "FOR", FORLOOP, ForLoop, 4, { NUMERIC_EXPR, NUMERIC_EXPR, NUMERIC_EXPR, ANY_EXPR } },
{ "HELP", PRHELP, PrintHelp, 1, { STRING_EXPR } },
{ "VARLIST", VARLIST, PrintObjectList, 0, { 0 } },
{ "ALIAS", ALIAS, AliasEdit, 2, { STRING_EXPR, STRING_EXPR } },
{ "BEEP", BEEP, GGTone, 2, { NUMERIC_EXPR, NUMERIC_EXPR } },
{ "EDIT", EDIT, DosEditFile, 1, { STRING_EXPR } },
{ "SYSTEM", SYSTEM, (VoidFuncIntPtr) DosSystem, 0, { 0 } },
{ "LOGFILE", LOGFILE, WndwLogPrint, 1, { NUMERIC_EXPR } },
{ "COLOR", COLOR, SetObjectColor, 2, { GEOM_EXPR, NUMERIC_EXPR } },
{ "SNOC", SNOC, SnocList, 2, { ANY_EXPR, OLST_EXPR } },
{ "ATTRIB", ATTRIB, SetObjectStrAttrib, 3, { GEOM_EXPR, STRING_EXPR, STRING_EXPR } },
{ "CLOSED", CLOSED, ViewSetClosed, 1, { NUMERIC_EXPR } }
};
int GenFuncTableSize = sizeof(GenFuncTable) / sizeof(GenFuncTableType);
ConstantTableType ConstantTable[] = {
{ "PI", M_PI },
{ "ON", 1.0 },
{ "TRUE", 1.0 },
{ "OFF", 0.0 },
{ "FALSE", 0.0 },
{ "COL", (double) CAGD_CONST_U_DIR },
{ "ROW", (double) CAGD_CONST_V_DIR },
{ "KV_OPEN", (double) KV_UNIFORM_OPEN },
{ "KV_FLOAT", (double) KV_UNIFORM_FLOAT },
{ "E2", (double) CAGD_PT_E2_TYPE },
{ "E3", (double) CAGD_PT_E3_TYPE },
{ "P2", (double) CAGD_PT_P2_TYPE },
{ "P3", (double) CAGD_PT_P3_TYPE },
{ "BLACK", (double) BLACK },
{ "BLUE", (double) BLUE },
{ "GREEN", (double) GREEN },
{ "CYAN", (double) CYAN },
{ "RED", (double) RED },
{ "MAGENTA", (double) MAGENTA },
{ "YELLOW", (double) YELLOW },
{ "WHITE", (double) WHITE },
{ "MSDOS", (double) MACHINE_MSDOS },
{ "SGI", (double) MACHINE_SGI },
{ "HP", (double) MACHINE_HP },
{ "SUN", (double) MACHINE_SUN },
{ "APOLLO", (double) MACHINE_APOLLO },
{ "UNIX", (double) MACHINE_UNIX },
};
int ConstantTableSize = sizeof(ConstantTable) / sizeof(ConstantTableType);
/*****************************************************************************
* Routine to do type checking to the given tree - return type if found one *
* or returns ERROR_EXPR if error in types was detected. *
*****************************************************************************/
IritExprType InptPrsrTypeCheck(ParseTree *Root, int Level)
{
IritExprType Right, Left, Result;
if (Level == 0 &&
Root->NodeKind != PARAMETER && /* What is allowed on top level. */
Root->NodeKind != EQUAL &&
!IS_GEN_FUNCTION(Root->NodeKind)) {
IPGlblEvalError = IE_ERR_NO_ASSIGNMENT;
strcpy(IPGlblCharData, "");
return ERROR_EXPR;
}
if (IS_NUM_FUNCTION(Root->NodeKind)) { /* Funcs which returns Real Type: */
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return NUMERIC_EXPR;
}
if (IS_GEN_FUNCTION(Root->NodeKind)) { /* Funcs which returns nothing: */
if (Level == 0) {
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return NO_EXPR;
}
else {
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
UpdateCharError("Procedure ", Root->NodeKind);
return ERROR_EXPR;
}
}
switch (Root->NodeKind) {
case VECTOR: /* Object functions which returns Vector Type: */
case STANGENT:
case CTANGENT:
case SNORMAL:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return VECTOR_EXPR;
case CTLPT: /* Object functions which returns Ctl Pt Type: */
case CEVAL:
case SEVAL:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return CTLPT_EXPR;
case ROTX:
case ROTY:
case ROTZ:
case TRANS:
case SCALE:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return MATRIX_EXPR;
case BOX:
case GBOX:
case CONE:
case CONE2:
case CYLIN:
case SPHERE:
case TORUS:
case CIRCPOLY:
case POLY:
case CROSSEC:
case CONVEX:
case GPOLYGON:
case GPOLYLINE:
case MERGEPOLY:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return POLY_EXPR;
case CBEZIER:
case CBSPLINE:
case CREFINE:
case CRAISE:
case CSURFACE:
case CMESH:
case CIRCLE:
case ARC:
case CREGION:
case CEDITPT:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return CURVE_EXPR;
case SBEZIER:
case SBSPLINE:
case SREFINE:
case SRAISE:
case RULEDSRF:
case BOOLSUM:
case SWEEPSRF:
case SREGION:
case SFROMCRVS:
case SEDITPT:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return SURFACE_EXPR;
case LOAD:
case NTH:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return ANY_EXPR;
case OFFSET:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return SURFACE_EXPR | CURVE_EXPR;
case SURFREV:
case EXTRUDE:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return SURFACE_EXPR | POLY_EXPR;
case LIST:
case SDIVIDE:
case CDIVIDE:
if (FuncParamMismatch(Root)) return ERROR_EXPR;
return OLST_EXPR;
case PLUS:
case MINUS:
case MULT:
case DIV:
case POWER:
Right = InptPrsrTypeCheck(Root->Right, Level+1);
Left = InptPrsrTypeCheck(Root->Left, Level+1);
if (Right == ERROR_EXPR || Left == ERROR_EXPR) return ERROR_EXPR;
if (!OverLoadTypeCheck(Root->NodeKind, Right, Left, &Result)) {
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
UpdateCharError("Operator ", Root->NodeKind);
return ERROR_EXPR;
}
else
return Result;
case UNARMINUS:
if ((Right = InptPrsrTypeCheck(Root->Right, Level+1)) == ERROR_EXPR)
return ERROR_EXPR;
else if (!OverLoadTypeCheck(Root->NodeKind, Right, NO_EXPR,
&Result)) {
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
UpdateCharError("Operator ", Root->NodeKind);
return ERROR_EXPR;
}
else
return Result;
case EQUAL:
if ((Right = InptPrsrTypeCheck(Root->Right, Level+1)) == ERROR_EXPR)
return ERROR_EXPR;
if (Root->Left->NodeKind != PARAMETER) {
IPGlblEvalError = IE_ERR_ASSIGN_LEFT_OP;
InptPrsrPrintTree(Root->Left, IPGlblCharData);
return ERROR_EXPR;
}
return Right;
case NUMBER:
return NUMERIC_EXPR;
case PARAMETER:
switch (Root->U.PObj->ObjType) {
case POLY_OBJ:
return POLY_EXPR;
case NUMERIC_OBJ:
return NUMERIC_EXPR;
case VECTOR_OBJ:
return VECTOR_EXPR;
case CTLPT_OBJ:
return CTLPT_EXPR;
case MATRIX_OBJ:
return MATRIX_EXPR;
case STRING_OBJ:
return STRING_EXPR;
case OBJ_LIST_OBJ:
return OLST_EXPR;
case CURVE_OBJ:
return CURVE_EXPR;
case SURFACE_OBJ:
return SURFACE_EXPR;
case UNDEF_OBJ:
IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
strcpy(IPGlblCharData, Root->U.PObj->Name);
return ERROR_EXPR;
}
IPGlblEvalError = IE_ERR_FATAL_ERROR;
sprintf(IPGlblCharData, "Object = %s, Type %d",
Root->U.PObj->Name, Root->U.PObj->ObjType);
return ERROR_EXPR;
case STRING:
return STRING_EXPR;
default: /* Should never happen. */
IPGlblEvalError = IE_ERR_FATAL_ERROR;
UpdateCharError("Token ", Root->NodeKind);
return ERROR_EXPR;
}
}
/* Disable the function with no prototype warning on Borland's compilers. */
#ifdef __BORLANDC__
#pragma warn -pro
#endif /* __BORLANDC__ */
/*****************************************************************************
* Routine to evaluate a value of a given tree root and parameter. *
* Note we change the tree itself during the evaluation process. *
* Also note we assume the tree is type checked (via InptPrsrTypeCheck rtn). *
*****************************************************************************/
ParseTree *InptPrsrEvalTree(ParseTree *Root, int Level)
{
char *ErrorMsg;
RealType R;
ParseTree *TempL, *TempR, *Params[5];
PolygonStruct *PPoly;
ObjectStruct *PObj;
switch (Root->NodeKind) {
case ARCSIN: /* Real return functions with one real parameter. */
case ARCCOS:
case ARCTAN:
case COS:
case EXP:
case FABS:
case LN:
case LOG:
case SIN:
case SQRT:
case TAN:
case TIME:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
(Params[0]->U.R);
Root->ObjType = NUMERIC_OBJ;
if (RetrieveMathError()) return NULL;
return Root;
case CPOLY:
case AREA:
case VOLUME:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
(Params[0]->U.PObj);
Root->ObjType = NUMERIC_OBJ;
if (RetrieveMathError()) return NULL;
return Root;
case ARCTAN2: /* Real return functions with two real parameters. */
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.R = (NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].Func)
(Params[0]->U.R, Params[1]->U.R);
Root->ObjType = NUMERIC_OBJ;
if (RetrieveMathError()) return NULL;
return Root;
case VECTOR: /* Object return functions with three real parameters. */
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
("", &Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R, NULL);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CTLPT:
case LIST:
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Root -> Right);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case ROTX:
case ROTY:
case ROTZ:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(&Params[0]->U.R);
if (RetrieveMathError()) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case TRANS:
case SCALE:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec);
if (RetrieveMathError()) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case BOX:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, &Params[1]->U.R, &Params[2]->U.R,
&Params[3]->U.R);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case GBOX:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, Params[1]->U.PObj ->U.Vec,
Params[2]->U.PObj->U.Vec, Params[3]->U.PObj ->U.Vec);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CONE:
case CYLIN:
case CIRCPOLY:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
&Params[2]->U.R);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SPHERE:
case CIRCLE:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, &Params[1]->U.R);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case TORUS:
case CONE2:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
&Params[2]->U.R, &Params[3]->U.R);
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SEVAL:
case SNORMAL:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case STANGENT:
case SREGION:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R,
&Params[2]->U.R, &Params[3]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CDIVIDE:
case CEVAL:
case CTANGENT:
case CRAISE:
case OFFSET:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SREFINE:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R,
&Params[2]->U.R, Params[3]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CREFINE:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R, Params[2]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SDIVIDE:
case SRAISE:
case CSURFACE:
case CREGION:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R, &Params[2]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CMESH:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj,
&Params[1]->U.R, &Params[2]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case NTH:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R);
if (Root->U.PObj == NULL) return NULL;
if (IS_NUM_OBJ(Root->U.PObj)) {
Root->ObjType = NUMERIC_OBJ;
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
Root->U.R = Root->U.PObj->U.R;
Root->NodeKind = NUMBER; /* Disconnect the var. binding. */
return Root;
}
else {
Root->ObjType = Root->U.PObj->ObjType;
/* Since at this point, no one is pointing on it: */
Root->U.PObj->Count = 0;
return Root;
}
case POLY:
case SBEZIER:
case CBEZIER:
case SURFREV:
case CONVEX:
case GPOLYGON:
case GPOLYLINE:
case SFROMCRVS:
case MERGEPOLY:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CBSPLINE:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(&Params[0]->U.R, Params[1]->U.PObj, Params[2]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SBSPLINE:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(&Params[0]->U.R, &Params[1]->U.R,
Params[2]->U.PObj, Params[3]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CROSSEC:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
Root->ObjType = POLY_OBJ;
/* Use table entries to call the function directly. */
if (IS_POLY_OBJ(Params[0] -> U.PObj))
Root->U.PObj =
(ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj);
else
Root->U.PObj =
(ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)(NULL);
if (Root->U.PObj == NULL) return NULL;
return Root;
case EXTRUDE:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj->U.Vec);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case RULEDSRF:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case BOOLSUM:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj,
Params[2]->U.PObj, Params[3]->U.PObj);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case CEDITPT:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj,
&Params[2]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SEDITPT:
if (!FetchParameters(Root, 4, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj,
&Params[2]->U.R, &Params[3]->U.R);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case ARC:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Vec, Params[1]->U.PObj->U.Vec,
Params[2]->U.PObj->U.Vec);
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SWEEPSRF:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
if (IS_NUM_NODE(Params[2])) {
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj, NULL,
&Params[2]->U.R);
}
else {
R = 1.0;
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj, Params[2]->U.PObj,
&R);
}
if (Root->U.PObj == NULL) return NULL;
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case LOAD:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
Root->U.PObj = (ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Str, "");
if (Root->U.PObj == NULL) {
DataPrsrParseError(&ErrorMsg);
IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
strcpy(IPGlblCharData, ErrorMsg);
return NULL;
}
Root->ObjType = Root -> U.PObj -> ObjType;
return Root;
case SNOC:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
if (Params[0]->ObjType == NUMERIC_OBJ) {
PObj = GenNumObject("", &Params[0]->U.R, NULL);
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(PObj, Params[1]->U.PObj);
MyFree((char *) PObj, ALLOC_OBJECT);
}
else {
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj, Params[1]->U.PObj);
}
Root->ObjType = UNDEF_OBJ;
return Root;
case VIEW:
case INTERACT:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
Root->ObjType = UNDEF_OBJ;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj, &Params[1]->U.R);
return Root;
case COLOR:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
Root->ObjType = UNDEF_OBJ;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj, REAL_TO_INT(Params[1]->U.R));
return Root;
case EXIT:
/* Yes - we finished for today... */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(0);
case PAUSE:
case LOGFILE:
case CLOSED:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(&Params[0] -> U.R);
Root->ObjType = UNDEF_OBJ;
return Root;
case VARLIST:
case SYSTEM:
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)(GlblObjList);
Root->ObjType = UNDEF_OBJ;
return Root;
case DIR:
case CHDIR:
case INCLUDE:
case PRHELP:
case EDIT:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Str);
Root->ObjType = UNDEF_OBJ;
return Root;
case SAVE:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
if (Params[1]->ObjType == NUMERIC_OBJ) {
PObj = GenNumObject("", &Params[1]->U.R, NULL);
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Str, PObj);
MyFree((char *) PObj, ALLOC_OBJECT);
}
else {
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Str, Params[1]->U.PObj);
}
if (DataPrsrParseError(&ErrorMsg) != 0) {
IPGlblEvalError = IE_ERR_DATA_PRSR_ERROR;
strcpy(IPGlblCharData, ErrorMsg);
return NULL;
}
Root->ObjType = UNDEF_OBJ;
return Root;
case BEEP:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(REAL_TO_INT(Params[0]->U.R), REAL_TO_INT(Params[1]->U.R));
Root->ObjType = UNDEF_OBJ;
return Root;
case ALIAS:
if (!FetchParameters(Root, 2, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj->U.Str, Params[1]->U.PObj->U.Str);
Root->ObjType = UNDEF_OBJ;
return Root;
case ATTRIB:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(Params[0]->U.PObj,
Params[1]->U.PObj->U.Str, Params[2]->U.PObj->U.Str);
Root->ObjType = UNDEF_OBJ;
return Root;
case FREEOBJ:
if (!FetchParameters(Root, 1, Level, Params)) return NULL;
if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
return NULL;
if (TempR->ObjType == NUMERIC_OBJ) {
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
strcpy(IPGlblCharData, "Func FREE, parameter 1");
return Root;
}
if (strlen(TempR->U.PObj->Name) == 0) {
IPGlblEvalError = IE_ERR_FREE_SIMPLE;
UpdateCharError("Procedure ", FREEOBJ);
return Root;
}
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(TempR->U.PObj);
Root->ObjType = UNDEF_OBJ;
TempR->U.PObj = NULL; /* Make sure its disconnected... */
return Root;
case NORMAL:
if (!FetchParameters(Root, 3, Level, Params)) return NULL;
/* Use table entries to call the function directly. */
(GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].Func)
(&Params[0]->U.R, &Params[1]->U.R, &Params[2]->U.R);
Root->ObjType = UNDEF_OBJ;
return Root;
case IFCOND:
IfCondition(FetchParameter(Root->Right, 0, 4),
FetchParameter(Root->Right, 1, 4),
FetchParameter(Root->Right, 2, 4),
FetchParameter(Root->Right, 3, 4));
Root->ObjType = UNDEF_OBJ;
return Root;
case FORLOOP:
ForLoop(FetchParameter(Root->Right, 0, 4),
FetchParameter(Root->Right, 1, 4),
FetchParameter(Root->Right, 2, 4),
FetchParameter(Root->Right, 3, 4));
Root->ObjType = UNDEF_OBJ;
return Root;
case PLUS:
case MINUS:
case MULT:
case DIV:
case POWER:
if (((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
|| ((TempL = InptPrsrEvalTree(Root->Left, Level+1)) == NULL))
return NULL;
TempR = OverLoadEvalOper(Root, TempR, TempL,
&IPGlblEvalError, IPGlblCharData);
if (RetrieveMathError())
return NULL;
else
return TempR;
case UNARMINUS:
if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
return NULL;
TempR = OverLoadEvalOper(Root, TempR, NULL,
&IPGlblEvalError, IPGlblCharData);
if (RetrieveMathError())
return NULL;
else
return TempR;
case NUMBER:
Root->ObjType = NUMERIC_OBJ;
return Root;
case PARAMETER:
if (Level == 0) { /* If only object - print its content. */
Root->U.PObj->Count--; /* Remove reference from this tree. */
PrintObject(Root->U.PObj);
Root->U.PObj->Count++; /* Add reference back. */
Root->ObjType = Root->U.PObj->ObjType;
return Root;
}
if (IS_NUM_OBJ(Root->U.PObj)) {
Root->ObjType = NUMERIC_OBJ;
Root->U.PObj->Count--;
Root->U.R = Root->U.PObj->U.R;
Root->NodeKind = NUMBER; /* Disconnect the var. binding. */
return Root;
}
else {
Root->ObjType = Root->U.PObj->ObjType;
return Root;
}
case STRING:
Root->ObjType = STRING_OBJ;
return Root;
case EQUAL:
if ((TempR = InptPrsrEvalTree(Root->Right, Level+1)) == NULL)
return NULL;
TempL = Root->Left;
PPoly = NULL;
if (IS_UNDEF_OBJ(TempL->U.PObj)) /* Its new object. */
InsertObject(TempL->U.PObj); /* Insert to global vars. */
else if (IS_POLY_OBJ(TempL->U.PObj)) /* If old var. was poly. */
PPoly = TempL->U.PObj->U.Pl.P;
if (IS_NUM_NODE(TempR)) {
TempL->ObjType = TempL->U.PObj->ObjType = NUMERIC_OBJ;
TempL->U.PObj->U.R = TempR->U.R;
}
else {
if (TempL -> U.PObj == TempR -> U.PObj) return TempR;/* A=A. */
TempL->ObjType = TempR->ObjType;
CopyObject(TempL->U.PObj, TempR->U.PObj, FALSE);
}
if (PPoly != NULL) MyFree((char *) (PPoly), ALLOC_POLYGON);
Root->ObjType = UNDEF_OBJ;
return TempR;
}
return NULL; /* Makes warning silent. */
}
/* Restore the function with no prototype warning on Borland's compilers. */
#ifdef __BORLANDC__
#pragma warn .pro
#endif /* __BORLANDC__ */
/*****************************************************************************
* Routine to print help on the given subject HelpHeader. *
* Note a match is if the HelpHeader in prefix of help file line. *
*****************************************************************************/
static void PrintHelp(char *HelpHeader)
{
int i;
char *Path, s[LINE_LEN];
FILE *f;
Path = searchpath(GlblHelpFileName);
if (strlen(HelpHeader) == 0)
HelpHeader = "Commands"; /* Print a list of all commands. */
if ((f = fopen(Path, "r")) == NULL) {
sprintf(s, "Cannot open help file \"%s\".\n", GlblHelpFileName);
WndwInputWindowPutStr(s);
return;
}
for (i = 0; i < (int) strlen(HelpHeader); i++)
if (islower(HelpHeader[i])) HelpHeader[i] = toupper(HelpHeader[i]);
while (fgets(s, LINE_LEN-1, f) != NULL) {
if (strncmp(HelpHeader, s, strlen(HelpHeader)) == 0) {
/* Found match - print it. */
while (fgets(s, LINE_LEN-1, f) != NULL && s[0] != '$') {
WndwInputWindowPutStr(&s[1]); /* Skip char 1. */
}
fclose(f);
return;
}
}
fclose(f);
sprintf(s, "No help on %s\n", HelpHeader);
WndwInputWindowPutStr(s);
}
/*****************************************************************************
* Routine to execute the IF structure. *
*****************************************************************************/
static void IfCondition(ParseTree *Left, ParseTree *Cond, ParseTree *Right,
ParseTree *PBody)
{
int i, NumOfExpr;
RealType L, R;
char *Str;
Left = InptPrsrEvalTree(Left, 1);
Cond = InptPrsrEvalTree(Cond, 1);
Right = InptPrsrEvalTree(Right, 1);
L = Left->U.R;
Str = Cond->U.PObj->U.Str;
R = Right->U.R;
if ((strcmp(Str, "=") == 0 && L == R) ||
(strcmp(Str, "<>") == 0 && L != R) ||
(strcmp(Str, "<=") == 0 && L <= R) ||
(strcmp(Str, ">=") == 0 && L >= R) ||
(strcmp(Str, ">") == 0 && L > R) ||
(strcmp(Str, "<") == 0 && L < R)) {
/* If we are here, then the condition holds: */
for (i = 0; i < (NumOfExpr = CountNumExpressions(PBody)); i++) {
InptPrsrEvalTree(FetchExpression(PBody, i, NumOfExpr), 0);
if (GlblWasCtrlBrk || /* async. break send from the user. */
IPGlblEvalError) break;
}
}
}
/*****************************************************************************
* Routine to execute the FOR structure loop. *
* Note that as InptPrsrEvalTree routine is destructive on its input tree, *
* we must make a copy of the body before executing it! *
* We wish we could access the loop variable directly, but the user might *
* be stupid and free it in the loop - so me must access it by name. *
*****************************************************************************/
static void ForLoop(ParseTree *PStart, ParseTree *PInc, ParseTree *PEnd,
ParseTree *PBody)
{
int i, NumOfExpr, LoopCount;
char *LoopVarName = NULL;
RealType LoopVar, StartVal, Increment, EndVal;
ParseTree *PTemp;
ObjectStruct *PLoopVar;
/* Find the only two cases where loop variable is allowed - when then */
/* given starting value is a parameter, or assignment to parameter... */
if (PStart -> NodeKind == PARAMETER)
LoopVarName = PStart -> U.PObj -> Name;
else if (PStart -> NodeKind == EQUAL &&
PStart -> Left -> NodeKind == PARAMETER) {
LoopVarName = PStart -> Left -> U.PObj -> Name;
/* Rebind the iteration variable to body - it might be new: */
RebindVariable(PBody, PStart -> Left -> U.PObj);
if (GetObject(LoopVarName) == NULL) /* It is really new. */
PStart -> Left -> U.PObj -> Count++;
}
PStart = InptPrsrEvalTree(PStart, 1); /* Evaluate starting value. */
PInc = InptPrsrEvalTree(PInc, 1); /* Evaluate increment value. */
PEnd = InptPrsrEvalTree(PEnd, 1); /* Evaluate end value. */
if (IPGlblEvalError ||
PStart == NULL || PInc == NULL || PEnd == NULL) return;
StartVal = PStart -> U.R;
Increment = PInc -> U.R;
EndVal = PEnd -> U.R;
NumOfExpr = CountNumExpressions(PBody); /* Num. of expr. in the body. */
for (LoopVar = StartVal, LoopCount = 0;
APX_EQ(LoopVar, EndVal) ||
(Increment > 0 ? LoopVar <= EndVal : LoopVar >= EndVal);
LoopVar += Increment, LoopCount++) {
if (GlblWasCtrlBrk || /* Async. break send from the user. */
IPGlblEvalError || GlblFatalError) return;
if (LoopVarName != NULL) {
if ((PLoopVar = GetObject(LoopVarName)) != NULL &&
IS_NUM_OBJ(PLoopVar))
PLoopVar -> U.R = LoopVar; /* Update loop var. */
else {
IPGlblEvalError = IE_ERR_MODIF_ITER_VAR;
strcpy(IPGlblCharData, LoopVarName);
}
}
for (i = 0; i < NumOfExpr; i++) {
PTemp = FetchExpression(PBody, i, NumOfExpr);
if (LoopCount == 0 && InptPrsrTypeCheck(PTemp, 0) == ERROR_EXPR)
return;
else {
if (LoopVar == EndVal) {
/* Use the original tree. Note we must evaluate the */
/* original tree at least once as ObjType's are updated. */
InptPrsrEvalTree(PTemp, 0); /* Eval as its top level... */
}
else {
PTemp = InptPrsrCopyTree(PTemp);
InptPrsrEvalTree(PTemp, 0); /* Eval as its top level... */
InptPrsrFreeTree(PTemp); /* Not needed any more. */
}
}
}
}
}
/*****************************************************************************
* Routine to create an OBJECT LIST object out of all parameters. *
*****************************************************************************/
static ObjectStruct *GenObjectList(ParseTree *PObjParams)
{
int i, NumOfParams;
ParseTree *Param;
ObjectStruct *PObj;
NumOfParams = CountNumParameters(PObjParams);
if (NumOfParams > MAX_OBJ_LIST) {
IPGlblEvalError = IE_ERR_LIST_TOO_LONG;
return NULL;
}
PObj = AllocObject("", OBJ_LIST_OBJ, NULL);
for (i = 0; i < NumOfParams; i++) {
if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
NumOfParams),
1)) == NULL) {
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
if (Param -> NodeKind == NUMBER ||
(Param -> NodeKind == UNARMINUS &&
Param -> ObjType == NUMERIC_OBJ)) {
/* This is a special case in which the data is saved in parse */
/* tree instead of as an underneath object - make an object! */
PObj -> U.PObjList[i] = AllocObject("", NUMERIC_OBJ, NULL);
PObj -> U.PObjList[i] -> U.R = Param -> U.R;
}
else {
if (Param -> U.PObj -> ObjType == UNDEF_OBJ) {
IPGlblEvalError = IE_ERR_UNDEF_OBJECT;
strcpy(IPGlblCharData, Param -> U.PObj -> Name);
PObj -> U.PObjList[i] = NULL;
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
PObj -> U.PObjList[i] = Param -> U.PObj;
Param -> U.PObj -> Count++; /* Increase number of references. */
}
}
if (NumOfParams < MAX_OBJ_LIST) PObj -> U.PObjList[NumOfParams] = NULL;
return PObj;
}
/*****************************************************************************
* Routine to create an Control Point Object out of all parameters. *
*****************************************************************************/
static ObjectStruct *CtlPtFromParams(ParseTree *PObjParams)
{
int i, NumPts, NumOfParams, PtType,
CoordCount = 0;
ParseTree *Param;
ObjectStruct *PObj;
NumOfParams = CountNumParameters(PObjParams);
PObj = AllocObject("", CTLPT_OBJ, NULL);
for (i = 0; i < NumOfParams; i++) {
if ((Param = InptPrsrEvalTree(FetchParameter(PObjParams, i,
NumOfParams),
1)) == NULL) {
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
if (Param -> ObjType != NUMERIC_OBJ) {
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
strcpy(IPGlblCharData, "Numeric data expected");
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
if (i == 0) {
PtType = PObj -> U.CtlPt.PtType = (CagdPointType) Param -> U.R;
switch (PtType) {
case CAGD_PT_E2_TYPE:
NumPts = 2;
CoordCount = 1;
break;
case CAGD_PT_E3_TYPE:
NumPts = 3;
CoordCount = 1;
break;
case CAGD_PT_P2_TYPE:
NumPts = 3;
break;
case CAGD_PT_P3_TYPE:
NumPts = 4;
break;
default:
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
strcpy(IPGlblCharData, "E2, E3, P2, P3 expected");
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
if (NumOfParams - 1 != NumPts) {
IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
sprintf(IPGlblCharData, "%d expected", NumPts);
MyFree((char *) PObj, ALLOC_OBJECT);
return NULL;
}
}
else
PObj -> U.CtlPt.Coords[CoordCount++] = Param -> U.R;
}
return PObj;
}
/*****************************************************************************
* Routine to count number of expressions seperated by a COLON are given *
* in the tree ROOT. This routine is similar to CountNumParameters below. *
*****************************************************************************/
static int CountNumExpressions(ParseTree *Root)
{
int i=1;
while (Root->NodeKind == COLON) {
i++;
Root = Root->Right;
}
return i;
}
/*****************************************************************************
* Routine to fetch the i expression out of a tree represent n expressions *
* (0 <= i < n) seperated by colonc. Similar to FetchParameter routine below. *
*****************************************************************************/
static ParseTree *FetchExpression(ParseTree *Root, int i, int n)
{
int j;
for (j = 0; j < i; j++) Root = Root->Right;
if (i == n - 1)
return Root;
else
return Root->Left;
}
/*****************************************************************************
* Routine to retrieve math error if was one. return TRUE if was error. *
*****************************************************************************/
static int RetrieveMathError(void)
{
int Error;
char *FuncName, *p;
#ifdef __MSDOS__
if ((Error = MathError(&FuncName)) != 0) {
switch (Error) {
case DOMAIN:
p = "DOMAIN";
break;
case SING:
p = "SING";
break;
case OVERFLOW:
p = "O.F.";
break;
case UNDERFLOW:
p = "U.F.";
break;
case TLOSS:
p = "TLOSS";
break;
default:
p = "Undef.";
break;
}
strcpy(IPGlblCharData, p);
strcat(IPGlblCharData, " error - func. ");
strcat(IPGlblCharData, FuncName);
IPGlblEvalError = IE_ERR_FP_ERROR;
return TRUE;
}
#endif /* __MSDOS__ */
return FALSE;
}
/*****************************************************************************
* Routine to count number of parameters where given: parameters are defined *
* as subtrees seperated by commas, i.e.: the infix form 1, 2, 3, 4 is *
* represented as [1, [2, [3, 4]]] in the tree supplied to this function and *
* 4 (number of parameters) is returned. *
*****************************************************************************/
static int CountNumParameters(ParseTree *Root)
{
int i = 1;
if (Root == NULL) return 0;
while (Root->NodeKind == COMMA) {
i++;
Root = Root->Right;
}
return i;
}
/*****************************************************************************
* Routine to fetch the i paramter out of a tree represent n parameters *
* (0 <= i < n). See CountNumParameters for more description of structure. *
* Note it is assumed the tree HAS n parameters and 0<=i<n (No input error). *
*****************************************************************************/
static ParseTree *FetchParameter(ParseTree *Root, int i, int n)
{
int j;
for (j = 0; j < i; j++) Root = Root->Right;
if (i == n - 1)
return Root;
else
return Root->Left;
}
/*****************************************************************************
* Routine to fetch the parameters from the parsed tree. *
* Returns TRUE iff fetching was succesfull. *
*****************************************************************************/
static int FetchParameters(ParseTree *Root, int NumParams, int Level,
ParseTree *Params[])
{
int i;
Level++;
for (i = 0; i < NumParams; i++)
if ((Params[i] = InptPrsrEvalTree(FetchParameter(Root->Right, i,
NumParams),
Level)) == NULL)
return FALSE;
return TRUE;
}
/*****************************************************************************
* Routine to test number of parameters and type of them against what is *
* defined in its global tables Num/Obj/GenFuncTable. return TRUE if mismatch *
* was detected: *
*****************************************************************************/
static int FuncParamMismatch(ParseTree *Root)
{
int FuncOffset, Count, i = Root->NodeKind / 100;
FuncTableType *FuncTable;
switch (i * 100) {
case NUM_FUNC: /* Numeric (real returned) functions. */
FuncOffset = Root->NodeKind-NUM_FUNC_OFFSET;
FuncTable = (FuncTableType *) NumFuncTable;
break;
case OBJ_FUNC: /* Object (returned) functions. */
FuncOffset = Root->NodeKind-OBJ_FUNC_OFFSET;
FuncTable = (FuncTableType *) ObjFuncTable;
break;
case GEN_FUNC:
FuncOffset = Root->NodeKind-GEN_FUNC_OFFSET;
FuncTable = (FuncTableType *) GenFuncTable;
break;
default:
IPGlblEvalError = IE_ERR_FATAL_ERROR;
UpdateCharError("Undefined function - ", Root->NodeKind);
return TRUE;
}
if (FuncTable[FuncOffset].NumOfParam == ANY_PARAM_NUM)
return FALSE;
/* See if number of parameters is ok: */
if ((Count = CountNumParameters(Root->Right)) !=
FuncTable[FuncOffset].NumOfParam) {
IPGlblEvalError = IE_ERR_NUM_PRM_MISMATCH;
sprintf(IPGlblCharData, "Func %s - %d expected, %d found",
FuncTable[FuncOffset].FuncName,
FuncTable[FuncOffset].NumOfParam,
Count);
return TRUE;
}
/* See if type of parameters is consistent: */
for (i = 0; i < Count; i++) {
if (FuncTable[FuncOffset].ParamObjType[i] != ANY_EXPR &&
!(FuncTable[FuncOffset].ParamObjType[i] &
InptPrsrTypeCheck(FetchParameter(Root->Right, i, Count), 1))) {
sprintf(IPGlblCharData, "Func %s,%sparameter %d",
FuncTable[FuncOffset].FuncName,
IPGlblEvalError == IE_ERR_UNDEF_OBJECT ? " undefined " : " ",
i+1);
IPGlblEvalError = IE_ERR_TYPE_MISMATCH;
return TRUE;
}
}
return FALSE;
}
/*****************************************************************************
* Routine to free a tree - release all memory allocated by it. *
*****************************************************************************/
void InptPrsrFreeTree(ParseTree *Root)
{
char s[LINE_LEN];
int ValidObject;
if (!Root) return;
ValidObject = Root->ObjType != NUMERIC_OBJ && Root->ObjType != UNDEF_OBJ;
if (IS_FUNCTION(Root -> NodeKind)) {
if (IS_NO_PARAM_FUNC(Root -> NodeKind))
MyExprFree(Root);
else {
InptPrsrFreeTree(Root->Right);
if (ValidObject && strlen(Root->U.PObj->Name) == 0)
MyFree((char *) Root->U.PObj, ALLOC_OBJECT); /* Its temp.*/
MyExprFree(Root);
}
return;
}
switch (Root -> NodeKind) {
case DIV:
case MINUS:
case MULT:
case PLUS:
case POWER:
InptPrsrFreeTree(Root->Right);
InptPrsrFreeTree(Root->Left);
if (ValidObject && strlen(Root->U.PObj->Name) == 0)
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
MyExprFree(Root);
break;
case UNARMINUS:
InptPrsrFreeTree(Root->Right);
if (ValidObject && strlen(Root->U.PObj->Name) == 0)
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* Its temporary.*/
MyExprFree(Root);
break;
case COMMA:
case COLON:
case EQUAL:
InptPrsrFreeTree(Root->Right);
InptPrsrFreeTree(Root->Left);
MyExprFree(Root);
break;
case NUMBER:
MyExprFree(Root);
break;
case PARAMETER:
if (Root->U.PObj) {
/* No assign took place - Its temporary. */
if ((Root->U.PObj->ObjType == UNDEF_OBJ ||
strlen(Root->U.PObj->Name) == 0))
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
else
Root->U.PObj->Count--;
}
MyExprFree(Root);
break;
case STRING:
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);/* The string object.*/
MyExprFree(Root);
break;
case TOKENSTART:
MyExprFree(Root);
break;
case OPENPARA:
case CLOSPARA:
MyExprFree(Root);
break;
default:
/* We might free partially build (by InptPrsr) tree when error */
/* is detected, and such tree may have nodes with NodeKind>=1000.*/
if (Root->NodeKind >= 1000) {
MyExprFree(Root);
}
else {
sprintf(s, "%s (%d).\n",
"InptPrsrFreeTree: Undefined ParseTree type to free",
Root -> NodeKind);
FatalError(s);
}
break;
}
}
/*****************************************************************************
* Routine to print a content of ROOT (using inorder traversal): *
* level holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations. *
* If *str = NULL print on stderr, else on given string Str. *
*****************************************************************************/
void InptPrsrPrintTree(ParseTree *Root, char *Str)
{
strcpy(IPGlblCharData, ""); /* Make the string empty. */
if (Str == NULL) {
strcpy(IPGlblCharData, ""); /* Make the string empty. */
LocalPrintTree(Root, 0, IPGlblCharData); /* Copy to local str. */
fprintf(stderr, IPGlblCharData); /* and print... */
}
else {
strcpy(Str, ""); /* Make the string empty. */
LocalPrintTree(Root, 0, Str); /* Dont print to stderr - copy to str. */
}
}
/*****************************************************************************
* Routine to print a content of ROOT (using inorder traversal): *
* level holds: 0 for lowest level +/-, 1 for *, /, 2 for ^ operations. *
* It is assumed Str has at list LINE_LEN_LONG places to write the expression.*
*****************************************************************************/
static void LocalPrintTree(ParseTree *Root, int Level, char *Str)
{
int CloseFlag = FALSE, Len, i;
if (!Root) return;
i = Root->NodeKind / 100;
if ((Len = strlen(Str)) > LINE_LEN_LONG * 2 / 3)/* Prevent from overflow.*/
if (Str[Len-1] == '.')
return; /* "..." was allready concatenated. */
else {
strcat(Str, "...");
return;
}
# ifdef DEBUG
strcat(Str, "["); /* Usefull to see ALL nestings - no preceedings. */
# endif /* DEBUG */
switch (i * 100) {
case NUM_FUNC:
Level = 0;
CloseFlag = TRUE;
strcat(Str, NumFuncTable[Root->NodeKind-NUM_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case OBJ_FUNC:
Level = 0;
CloseFlag = TRUE;
strcat(Str, ObjFuncTable[Root->NodeKind-OBJ_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case GEN_FUNC:
Level = 0;
CloseFlag = TRUE;
strcat(Str, GenFuncTable[Root->NodeKind-GEN_FUNC_OFFSET].FuncName);
strcat(Str, "(");
break;
case OPERATORS:
switch (Root->NodeKind) {
case DIV:
if (Level > 1) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 1; /* Div Level. */
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "/");
break;
case MINUS:
if (Level > 0) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 0; /* Minus Level. */
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "-");
break;
case MULT:
if (Level > 1) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 1; /* Mul Level. */
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "*");
break;
case PLUS:
if (Level > 0) {
strcat(Str, "(");
CloseFlag = TRUE;
}
Level = 0; /* Plus Level. */
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "+");
break;
case POWER:
Level = 2; /* Power Level. */
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "^");
break;
case UNARMINUS:
strcat(Str, "(-");
Level = 0;
CloseFlag = TRUE;
break;
case COMMA:
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, ",");
break;
case COLON:
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, ":");
break;
case EQUAL:
LocalPrintTree(Root->Left, Level, Str);
strcat(Str, "=");
break;
case NUMBER:
sprintf(&Str[strlen(Str)], "%lg", Root->U.R);
break;
case PARAMETER:
sprintf(&Str[strlen(Str)], "%s", Root->U.PObj->Name);
break;
case STRING:
sprintf(&Str[strlen(Str)], "\"%s\"", Root->U.PObj->U.Str);
break;
case OPENPARA:
strcat(Str, "(");
break;
case CLOSPARA:
strcat(Str, ")");
break;
case TOKENSTART:
break;
default:
FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
}
break;
default:
FatalError("LocalPrintTree: Undefined ParseTree type to print, exit");
}
LocalPrintTree(Root->Right, Level, Str);
if (CloseFlag) strcat(Str, ")");
# ifdef DEBUG
strcat(Str, "]"); /* Usefull to see ALL nestings - no preceedings. */
# endif /* DEBUG */
}
/*****************************************************************************
* Routine to copy a parse tree - Generate brand new ParseTree structure *
* but bind to non-temp variables if they are exists - their Name is not NULL *
* This means that updating these objects in the copied tree, will affect *
* these objects in the original tree. *
*****************************************************************************/
ParseTree *InptPrsrCopyTree(ParseTree *Root)
{
ParseTree *NewRoot;
if (Root == NULL) return NULL;
NewRoot = MyExprMalloc();
if (IS_FUNCTION(Root->NodeKind)) { /* All the functions. */
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> ObjType = Root -> ObjType;
NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
return NewRoot;
}
switch (Root->NodeKind) {
case DIV:
case MINUS:
case MULT:
case PLUS:
case POWER:
case COMMA:
case COLON:
case EQUAL:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> ObjType = Root -> ObjType;
NewRoot -> Right = InptPrsrCopyTree(Root -> Right);
NewRoot -> Left = InptPrsrCopyTree(Root -> Left);
return NewRoot;
case NUMBER:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> ObjType = Root -> ObjType;
NewRoot -> U.R = Root -> U.R;
return NewRoot;
case PARAMETER:
case STRING:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> ObjType = Root -> ObjType;
NewRoot -> U.PObj = Root -> U.PObj; /* Point on SAME object. */
NewRoot -> U.PObj -> Count++; /* But increase its ref. count. */
return NewRoot;
case TOKENSTART:
NewRoot -> NodeKind = Root -> NodeKind;
NewRoot -> ObjType = Root -> ObjType;
return NewRoot;
default:
FatalError("InptPrsrCopyTree: Undefined ParseTree type to copy, exit\n");
}
return NULL; /* Makes warning silent. */
}
/*****************************************************************************
* Routine to rebind a variable - given a tree, scan it and update each *
* occurance of that variable to point to PObj. *
*****************************************************************************/
static void RebindVariable(ParseTree *Root, ObjectStruct *PObj)
{
if (Root == NULL) return;
if (IS_FUNCTION(Root->NodeKind)) { /* All the functions. */
RebindVariable(Root -> Right, PObj);
return;
}
switch (Root->NodeKind) {
case UNARMINUS:
RebindVariable(Root -> Right, PObj);
return;
case DIV:
case MINUS:
case MULT:
case PLUS:
case POWER:
case COMMA:
case COLON:
case EQUAL:
RebindVariable(Root -> Right, PObj);
RebindVariable(Root -> Left, PObj);
return;
case NUMBER:
return;
case PARAMETER:
case STRING:
if (strcmp(Root -> U.PObj -> Name, PObj -> Name) == 0) {
/* I wish I could free that, but nesting loops might try */
/* to free the same place n times... We will loose this */
/* variable place if it defined for the first time. Fix */
/* it if you really care... */
/*
if (IS_UNDEF_OBJ(Root -> U.PObj))
MyFree((char *) Root->U.PObj, ALLOC_OBJECT);
*/
Root -> U.PObj = PObj;
}
return;
case TOKENSTART:
return;
default:
FatalError("RebindVariable: Undefined ParseTree type, exit\n");
}
}
/*****************************************************************************
* Routine to return evaluation error if happen one, zero elsewhere *
*****************************************************************************/
InptPrsrEvalErrType InptPrsrEvalError(char **Message)
{
InptPrsrEvalErrType Temp;
*Message = IPGlblCharData;
Temp = IPGlblEvalError;
IPGlblEvalError = IPE_NO_ERR;
return Temp;
}